/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef OHMW_FRAMEWORK_CXX_BINCODE_ENDIAN_H
#define OHMW_FRAMEWORK_CXX_BINCODE_ENDIAN_H

#include <algorithm>
#include <cstdint>

namespace OHOS {
namespace OHMW {
template<typename T, unsigned int N>
struct swap_bytes {
    static T call(T value) {
        union { T a; uint8_t b[N]; };
        a = value;
        std::reverse(b, b + N);
        return a;
    }
};

template<typename T>
struct swap_bytes<T, 1> {
    static T call(T value) {
        return value;
    }
};

template<typename T>
struct swap_bytes<T, 2> {
    static T call(T value) {
        union { T a; uint16_t b; };
        a = value;
        b = __builtin_bswap16(b);
        return a;
    }
};

template<typename T>
struct swap_bytes<T, 4> {
    static T call(T value) {
        union { T a; uint32_t b; };
        a = value;
        b = __builtin_bswap32(b);
        return a;
    }
};

template<typename T>
struct swap_bytes<T, 8> {
    static T call(T value) {
        union { T a; uint64_t b; };
        a = value;
        b = __builtin_bswap64(b);
        return a;
    }
};

template<typename T>
inline T swap_if_le(T value) {
    if constexpr (__BYTE_ORDER == __LITTLE_ENDIAN) {
        return swap_bytes<T, sizeof(T)>::call(value);
    } else {
        return value;
    }
}

template<typename T>
inline T swap_if_be(T value) {
    if constexpr (__BYTE_ORDER == __BIG_ENDIAN) {
        return swap_bytes<T, sizeof(T)>::call(value);
    } else {
        return value;
    }
}

template<typename T>
inline std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, T> host2be(T value) {
    return swap_if_le(value);
}

template<typename T>
inline std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, T> be2host(T value) {
    return swap_if_le(value);
}

template<typename T>
inline std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, T> host2le(T value) {
    return swap_if_be(value);
}

template<typename T>
inline std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, T> le2host(T value) {
    return swap_if_be(value);
}
}
}

#endif
